﻿using NugetHelper.Properties;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using org.ropean.Extensions.Common;

namespace NugetHelper
{
  public partial class FrmMain : Form
  {
    public FrmMain()
    {
      InitializeComponent();

      ToggleUI();
    }

    #region Core

    void ToggleUI()
    {
      bool noApiKey = string.IsNullOrEmpty(ApiKey);

      txtApiKey.Visible = btnSetApiKey.Visible = noApiKey;

      txtProject.Visible = btnChooseProject.Visible = btnPushPackage.Visible = !noApiKey;
    }

    string _apiKey;

    const string _apiSettingKey = "apiKey";

    public string ApiKey
    {
      get
      {
        if (string.IsNullOrEmpty(_apiKey))
        {
          _apiKey = ConfigurationManager.AppSettings[_apiSettingKey];

          if (!string.IsNullOrEmpty(_apiKey))
          {
            try
            {
              _apiKey = _apiKey.Decrypt();
            }
            catch
            {
              ApiKey = _apiKey;
            }
          }
        }

        return _apiKey;
      }
      set
      {
        _apiKey = value.Encrypt();

        //Create the object
        var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

        var settings = config.AppSettings.Settings;

        if (settings.AllKeys.Contains(_apiSettingKey))
        {
          settings[_apiSettingKey].Value = _apiKey;
        }
        else
        {
          settings.Add(_apiSettingKey, _apiKey);
        }

        //save to apply changes
        config.Save(ConfigurationSaveMode.Modified);

        //ConfigurationManager.RefreshSection("appSettings");
      }
    }

    public static string NugetSource
    {
      get
      {
        return ConfigurationManager.AppSettings["nugetSource"];
      }
    }

    /*
     * 获取程序的基目录
     * System.AppDomain.CurrentDomain.BaseDirectory
     * 
     * 获取模块的完整路径
     * System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName
     * 
     * 获取和设置当前目录(该进程从中启动的目录)的完全限定目录
     * System.Environment.CurrentDirectory
     * 
     * 获取应用程序的当前工作目录
     * System.IO.Directory.GetCurrentDirectory()
     * 
     * 获取和设置包括该应用程序的目录的名称
     * System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase
     * 
     * 获取启动了应用程序的可执行文件的路径
     * System.Windows.Forms.Application.StartupPath
     * 
     * 获取启动了应用程序的可执行文件的路径及文件名
     * System.Windows.Forms.Application.ExecutablePath
     * 
     */

    const string NugetName = "nuget.exe";

    Dictionary<string, string> Extensions = new Dictionary<string, string>
    {
      { "Visual C# Project File", ".csproj" }
    };

    void AppendMessage(string message)
    {
      if (string.IsNullOrEmpty(txtMessage.Text))
      {
        txtMessage.AppendText(message);
      }
      else
      {
        txtMessage.AppendText(Environment.NewLine);

        txtMessage.AppendText(message);
      }
    }

    string CurrentDirectory
    {
      get
      {
        return System.Environment.CurrentDirectory;
      }
    }

    string ReleaseNuget()
    {
      string nugetPath = Path.Combine(CurrentDirectory, NugetName);

      if (File.Exists(nugetPath))
      {
        return nugetPath;
      }

      using (FileStream fileStream = new FileStream(nugetPath, FileMode.OpenOrCreate))
      {
        fileStream.Write(Resources.nuget_exe, 0, Resources.nuget_exe.Length);
      }

      return nugetPath;
    }

    void ExecuteNugetCommand(string command, string arguments, Action nextStep)
    {
      AppendMessage(string.Concat(command, " ..."));

      var nugetPath = ReleaseNuget();

      Task.Factory.StartNew(() =>
      {
        Process process = new Process();
        process.StartInfo.FileName = nugetPath;

        process.StartInfo.CreateNoWindow = true;         // 不创建新窗口    
        process.StartInfo.UseShellExecute = false;       //不启用shell启动进程  
        process.StartInfo.RedirectStandardInput = true;  // 重定向输入    
        process.StartInfo.RedirectStandardOutput = true; // 重定向标准输出    
        process.StartInfo.RedirectStandardError = true;  // 重定向错误输出

        process.StartInfo.Arguments = arguments;//“/C”表示执行完命令后马上退出 

        //AppendMessage(string.Format("{0} {1}", nugetPath, arguments));

        bool started = process.Start(); //启动

        if (started)
        {
          string message = process.StandardOutput.ReadToEnd();//获取返回值 

          AppendMessage(message);

          process.WaitForExit();//等待程序执行完退出进程 
        }

        process.Close();//结束 

        if (started)
        {
          nextStep?.Invoke();
        }
      });
    }

    void PushPackage(string package)
    {
      ExecuteNugetCommand("Push package", string.Format("push {0} -ApiKey {1} -Source {2}", package, ApiKey, NugetSource), () =>
      {
        btnPushPackage.Enabled = true;

      });
    }

    void SelectPackageToPush()
    {
      var projectName = Path.GetFileNameWithoutExtension(txtProject.Text.Trim());

      var packages = Directory.GetFiles(CurrentDirectory, "*.nupkg", SearchOption.TopDirectoryOnly)
        .Where(d => Path.GetFileName(d).StartsWith(projectName))
        .ToList();

      if (packages.Count > 1)
      {
        var package = packages.OrderBy(d => Path.GetFileNameWithoutExtension(d).Substring(projectName.Length)).LastOrDefault();

        PushPackage(package);
      }
      else
      {
        PushPackage(packages.FirstOrDefault());
      }
    }

    #endregion

    private void btnSetApiKey_Click(object sender, EventArgs e)
    {
      btnSetApiKey.Enabled = false;

      var apiKey = txtApiKey.Text.Trim();

      ApiKey = apiKey;

      AppendMessage("Set Api successfully.");

      ToggleUI();

      //ExecuteNugetCommand("SetApiKey", string.Format("setApiKey {0}", apiKey), null);
    }

    private void btnPushPackage_Click(object sender, EventArgs e)
    {
      btnPushPackage.Enabled = false;

      txtMessage.Clear();

      ExecuteNugetCommand("Pack project", string.Format("pack {0}", txtProject.Text.Trim()), SelectPackageToPush);
    }

    private void btnChooseProject_Click(object sender, EventArgs e)
    {
      var filter = string.Join("|", Extensions.Select(kv => string.Format("{0}|*{1}", kv.Key, kv.Value)));

      OpenFileDialog openFileDialog1 = new OpenFileDialog()
      {
        Filter = filter
      };

      if (openFileDialog1.ShowDialog() == DialogResult.OK)
      {
        txtProject.Text = openFileDialog1.FileName;
      }
    }

    private void txtApiKey_TextChanged(object sender, EventArgs e)
    {
      btnSetApiKey.Enabled = txtApiKey.Text.Trim().Length > 0;
    }

    private void txtProject_TextChanged(object sender, EventArgs e)
    {
      string projectPath = txtProject.Text.Trim();

      if (File.Exists(projectPath))
      {
        string projectExtension = Path.GetExtension(projectPath);

        btnPushPackage.Enabled = !string.IsNullOrEmpty(Extensions.FirstOrDefault(kv => kv.Value.Equals(projectExtension, StringComparison.CurrentCultureIgnoreCase)).Key);
      }
      else
      {
        btnPushPackage.Enabled = false;
      }
    }

    private void txtMessage_TextChanged(object sender, EventArgs e)
    {
      txtMessage.SelectionStart = txtMessage.Text.Length;
      txtMessage.SelectionLength = 0;
      txtMessage.ScrollToCaret();
    }
  }
}